package com.mobileseed.weather.util;

import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class CityLocator {

	/**
	 * 借助Google MAP 通过用户当前经纬度 获得用户当前城市
	 */
	static final String GOOGLE_MAPS_API_KEY = "abcdefg";

	private LocationManager locationManager;
	private Location currentLocation;
	private LocationListener locationlistener;
	private String city = null;

	public CityLocator(Context context) {

		this.locationManager = (LocationManager) context
				.getSystemService(Context.LOCATION_SERVICE);

		// GPS定位不可用则使用网络定位
		currentLocation = locationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);

		if (currentLocation == null)
			currentLocation = locationManager
					.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

		if (currentLocation == null) {
			locationlistener = new LocationListener() {

				@Override
				public void onLocationChanged(Location location) {
					currentLocation = location;
				}

				@Override
				public void onProviderDisabled(String provider) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onProviderEnabled(String provider) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onStatusChanged(String provider, int status,
						Bundle extras) {
					// TODO Auto-generated method stub

				}
			};

			locationManager
					.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
							1000, 0, locationlistener);
		}
	}

	/**
	 * 开始解析
	 */
	public void start() {
		new Thread() {
			public void run() {
				try {
					while (currentLocation == null) {
						Thread.sleep(1000);
						continue;
					}

					String temp = reverseGeocode(currentLocation);
					if (temp != null && temp.length() >= 2)
						city = temp;
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}

	/**
	 * 获得城市
	 * 
	 * @return
	 */
	public String getCity() {
		return city;
	}

	/**
	 * 通过Google map api 解析出城市
	 * 
	 * @param loc
	 * @return
	 */
	public String reverseGeocode(Location loc) {
		// http://maps.google.com/maps/geo?q=40.714224,-73.961452&output=json&oe=utf8&sensor=true_or_false&key=your_api_key
		String localityName = "";
		HttpURLConnection connection = null;
		URL serverAddress = null;

		try {
			// build the URL using the latitude & longitude you want to lookup
			// NOTE: I chose XML return format here but you can choose something
			// else
			serverAddress = new URL("http://maps.google.com/maps/geo?q="
					+ Double.toString(loc.getLatitude()) + ","
					+ Double.toString(loc.getLongitude())
					+ "&output=xml&oe=utf8&sensor=true&key="
					+ GOOGLE_MAPS_API_KEY);
			// set up out communications stuff
			connection = null;

			// Set up the initial connection
			connection = (HttpURLConnection) serverAddress.openConnection();
			connection.setRequestMethod("GET");
			connection.setDoOutput(true);
			connection.setReadTimeout(10000);

			connection.connect();

			try {
				InputStreamReader isr = new InputStreamReader(
						connection.getInputStream());
				InputSource source = new InputSource(isr);
				SAXParserFactory factory = SAXParserFactory.newInstance();
				SAXParser parser = factory.newSAXParser();
				XMLReader xr = parser.getXMLReader();
				GoogleReverseGeocodeXmlHandler handler = new GoogleReverseGeocodeXmlHandler();

				xr.setContentHandler(handler);
				xr.parse(source);

				localityName = handler.getLocalityName();
				System.out.println("GetCity.reverseGeocode()" + localityName);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			System.out.println("GetCity.reverseGeocode()" + ex);
		}

		return localityName;
	}

	/**
	 * The final piece of this puzzle is parsing the xml that is returned from
	 * google’s service. For this example I am using the java SAX (simple api
	 * for xml) parser. The final class to show here is
	 * GoogleReverseGeocodeXmlHandler. In my example, I only want the name of
	 * the city the user is in, so my XmlHandler class I’m about to show only
	 * parses that piece of information. If you want to grab more complete
	 * information (I’ll also give an example file that contains the XML
	 * returned by Google), you’ll have to add more to this class
	 * 
	 * @author Administrator
	 * 
	 */
	public class GoogleReverseGeocodeXmlHandler extends DefaultHandler {
		private boolean inLocalityName = false;
		private boolean finished = false;
		private StringBuilder builder;
		private String localityName;

		public String getLocalityName() {
			return this.localityName;
		}

		@Override
		public void characters(char[] ch, int start, int length)
				throws SAXException {
			super.characters(ch, start, length);
			if (this.inLocalityName && !this.finished) {
				if ((ch[start] != '\n') && (ch[start] != ' ')) {
					builder.append(ch, start, length);
				}
			}
		}

		@Override
		public void endElement(String uri, String localName, String name)
				throws SAXException {
			super.endElement(uri, localName, name);

			if (!this.finished) {
				if (localName.equalsIgnoreCase("LocalityName")) {
					this.localityName = builder.toString();
					this.finished = true;
				}

				if (builder != null) {
					builder.setLength(0);
				}
			}
		}

		@Override
		public void startDocument() throws SAXException {
			super.startDocument();
			builder = new StringBuilder();
		}

		@Override
		public void startElement(String uri, String localName, String name,
				Attributes attributes) throws SAXException {
			super.startElement(uri, localName, name, attributes);

			if (localName.equalsIgnoreCase("LocalityName")) {
				this.inLocalityName = true;
			}
		}
	}
}
